Machines run machine code.
But writing machine code is not particularly pleasant. It's very fiddly, and easy to get wrong. Unfortunately, machines run machine code, not other forms of code. Grace Hopper pioneered a solution to this problem; she worked out that it was possible to design other forms of code, which were easier to write certain classes of problems (e.g. code for processing financial transactions, which doesn't need exact control ove how every bit is layed out on the machine) and then "translate" that code into machine code.
This is the essence of a compiler. It turns programs into machine code.
program -> compiler -> machine code
There are also "interpreters". Instead of feeding in the entire program and then generating the appropriate machine code, they start with the entry point (maybe the first line) of the program, and then run all the lines of the program whenever it needs to.
practice questions
- Which of these descriptions would apply to a compiler?
- A: runs through a program line by line, and runs each line as soon as it reads it
- B: takes an entire program and translates it in its entirety into machine code, which can then be executed
- C: takes a series of abbreviations for specific machine code instructions and replaces them with the corresponding machine code
- Consider the program below, and decide (with a reason for each) which of a compiler, assembler or interpreter you could use in order to run it.
function f(x)
return x * x
endfunction
- Consider this program (taken from this resource) and explain whether an assembler would be a suitable device to translate it.
; ----------------------------------------------------------------------------------------
; Writes "Hello, World" to the console using only system calls. Runs on 64-bit Linux only.
; To assemble and run:
;
; nasm -felf64 hello.asm && ld hello.o && ./a.out
; ----------------------------------------------------------------------------------------
global _start
section .text
_start: mov rax, 1 ; system call for write
mov rdi, 1 ; file handle 1 is stdout
mov rsi, message ; address of string to output
mov rdx, 13 ; number of bytes
syscall ; invoke operating system to do the write
mov rax, 60 ; system call for exit
xor rdi, rdi ; exit code 0
syscall ; invoke operating system to exit
section .data
message: db "Hello, World", 10 ; note the newline at the end
Note – if you would like solutions you can try the exercises in a self-marking form on stepik.org.
further reading
- A [tutorial on writing x86_64 - i.e. most Intel processor - assembly language]
- Engineering A Compiler
- Software Foundations